import re
import enum
import struct
import ctypes
import sys
SP_RE = re.compile(r"\s*,\s*")

def bitfield(lo, hi):
    return property(lambda self: self.get_part(lo, hi), lambda self, x: self.set_part(lo, hi, x))
def sbitfield(lo, hi):
    return property(lambda self: self.get_spart(lo, hi), lambda self, x: self.set_part(lo, hi, x))

# def mbitfield(*args):
#     return property(lambda self: self.get_parts(*args), lambda self, x: self.set_parts(*args, x))
class Inst:
    def __init__(self, inst):
        self.inst = inst

    def set_part(self, lo, hi, val):
        hi = hi + 1
        mask = ((1 << (hi - lo)) - 1) << lo
        self.inst &= ~mask
        self.inst |= ((val << lo) & mask)

    def get_part(self, lo, hi):
        hi = hi + 1
        return (self.inst >> lo) & ((1 << (hi - lo)) - 1)
    def get_spart(self, lo, hi):
        hi = hi + 1
        val = (self.inst >> lo) & ((1 << (hi - lo)) - 1)
        if val & (1 << (hi - lo - 1)):
            val = val - (1 << (hi - lo))
        return val

    op = bitfield(26, 31)
    def format(self, dec):
        def hstr(v):
            if type(v) == int:
                return "0x%x" % v
            return v
        return dec[0] + '\t' + ",".join(map(hstr, dec[1:]))
    def decode(self):
        instword = lookup_inst_by_bin(self.inst)
        dec = instword.decode(self)
        return self.format(dec)
        # return self.op, self.ic
class SpecInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    func = bitfield(10, 15)
    rc = bitfield(5, 9)
    ic = bitfield(5, 9)
    rd = bitfield(0, 4)

class ChannelInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    ib = bitfield(13, 20)
    func = bitfield(10, 12)
    rc = bitfield(5, 9)
    rd = bitfield(0, 4)


class MiscInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    func = bitfield(0, 15)

class CSRInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    func = bitfield(8, 15)
    index = bitfield(0, 7)

class MatchInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    func = bitfield(10, 15)
    ic = bitfield(5, 9)
    rd = bitfield(0, 4)

class AtomInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    func = bitfield(12, 15)
    disp = sbitfield(0, 11)

class MemInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    disp = sbitfield(0, 15)
    def format(self, dec):
        #print(dec)
        return "%s\t%s,%d(%s)" % tuple(dec)
class JmpInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    disp = sbitfield(0, 15)
    def format(self, dec):
        #print(dec, file=sys.stderr)
        return "%s\t%s,(%s),%d" % tuple(dec)

class Int2Inst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    ib = bitfield(13, 20)
    func = bitfield(5, 12)
    rc = bitfield(0, 4)

class Int3Inst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    ic = bitfield(13, 20)
    func = bitfield(10, 12)
    rc = bitfield(5, 9)
    rd = bitfield(0, 4)

class Log3Inst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    index = bitfield(10, 15)
    rc = bitfield(5, 9)
    rd = bitfield(0, 4)


class Fp2Inst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    ib = bitfield(13, 20)
    func = bitfield(5, 12)
    rc = bitfield(0, 4)


class Fp3Inst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    func = bitfield(10, 15)
    rc = bitfield(5, 9)
    rd = bitfield(0, 4)


class Vec2Inst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    ib = bitfield(13, 20)
    func = bitfield(5, 12)
    rc = bitfield(0, 4)


class Vec3Inst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    func = bitfield(10, 15)
    rc = bitfield(5, 9)
    ic = bitfield(5, 9)
    rd = bitfield(0, 4)


class UnalnInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    func = bitfield(12, 15)
    disp = sbitfield(0, 11)


class RCInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    func = bitfield(8, 15)
    idest = bitfield(0, 7)


class BrInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    disp = sbitfield(0, 20)
    def decode_with_pc(self, pc):
        instword = lookup_inst_by_bin(self.inst)
        dec = instword.decode(self)
        return "%s\t%s,%x" % (dec[0], dec[1], (dec[2] + 1) * 4 + pc)
class VShffIcInst(Inst):
    op = bitfield(26, 31)
    ra = bitfield(21, 25)
    rb = bitfield(16, 20)
    func = bitfield(13, 15)  # 0x5
    ic = bitfield(5, 12)
    rd = bitfield(0, 4)
OPCLASS = {
    0x0: SpecInst,
    0x3: JmpInst,
    0x4: BrInst,
    0x5: ChannelInst,
    0x6: MiscInst,
    0x7: MatchInst,
    0x8: AtomInst,
    0x9: MemInst,
    0xa: MemInst,
    0xb: MemInst,
    0xc: MemInst,
    0xd: MemInst,
    0xe: MemInst,
    0xf: MemInst,
    0x10: Int2Inst,
    0x11: Int3Inst,
    0x12: Int2Inst,
    0x13: Int3Inst,
    0x17: Log3Inst,
    0x18: Fp2Inst,
    0x19: Fp3Inst,
    0x1a: Vec2Inst,
    0x1b: Vec3Inst,
    0x1f: Log3Inst,
    0x20: MemInst,
    0x21: MemInst,
    0x22: MemInst,
    0x23: MemInst,
    0x26: MemInst,
    0x28: MemInst,
    0x29: MemInst,
    0x2a: MemInst,
    0x2b: MemInst,
    0x2e: MemInst,
    0x24: MemInst,
    0x27: MemInst,
    0x2c: MemInst,
    0x2f: MemInst,
    0x25: UnalnInst,
    0x1c: UnalnInst,
    0x2d: RCInst,
    0x30: BrInst,
    0x31: BrInst,
    0x32: BrInst,
    0x33: BrInst,
    0x34: BrInst,
    0x35: BrInst,
    0x38: BrInst,
    0x39: BrInst,
    0x3a: BrInst,
    0x3b: BrInst,
    0x3c: BrInst,
    0x3d: BrInst,
    0x3e: MemInst,
    0x3f: MemInst
}
class ArgType(enum.Enum):
    RA = enum.auto()
    RB = enum.auto()
    RC = enum.auto()
    RD = enum.auto()
    IB = enum.auto()
    IC = enum.auto()
    DISP = enum.auto()
    INDEX = enum.auto()

STRARG = {
    "ra": ArgType.RA,
    "rb": ArgType.RB,
    "rc": ArgType.RC,
    "rd": ArgType.RD,
    "ib": ArgType.IB,
    "ic": ArgType.IC,
    "index": ArgType.INDEX,
    "disp": ArgType.DISP
}

REGNAME = 'v0,t0,t1,t2,t3,t4,t5,t6,t7,s0,s1,s2,s3,s4,s5,fp,a0,a1,a2,a3,a4,a5,t8,t9,t10,t11,ra,t12,at,gp,sp,zero'.split(",")
class InstWord:
    def __init__(self, name, args, op, func=None):
        self.name = name
        self.args = []
        for arg in SP_RE.split(args):
            if arg in STRARG:
                self.args.append(STRARG[arg])
            elif arg == 'disp(rb)':
                self.args.extend((ArgType.DISP, ArgType.RB))
        self.inst_class = get_class_by_op_func(op, func)
    def decode(self, inst):
        ret = [self.name]
        for arg in self.args:
            attrval = getattr(inst, arg.name.lower())
            if arg.name.lower().startswith('r'):
                attrval = REGNAME[attrval]
            ret.append(attrval)
        return ret
        #print(self.name, self.args)

def get_class_by_bin(inst):
    op = (inst >> 26) & 63
    if op == 0x6:
        misc = MiscInst(inst)
        if misc.func & 0xf000:
            return CSRInst
    elif op == 0x1b:
        vec3 = Vec3Inst(inst)
        if vec3.func & 0x28:
            return VShffIcInst
    return OPCLASS[op]
def get_class_by_op_func(op, func):
    if func is not None:
        if op == 0x6 and (func & 0xf000):
            return CSRInst
        elif op == 0x1b and (func & 0x28):
            return VShffIcInst
    return OPCLASS[op]

OPINST = {
    0x3: InstWord('jmp', 'ra, rb, disp', 0x3),
    0x4: InstWord('br', 'ra, disp', 0x4),
    0x9: InstWord('ldwe', 'ra, disp(rb)', 0x9),
    0xa: InstWord('ldse', 'ra, disp(rb)', 0xa),
    0xb: InstWord('ldde', 'ra, disp(rb)', 0xb),
    0xc: InstWord('vlds', 'ra, disp(rb)', 0xc),
    0xd: InstWord('vldd', 'ra, disp(rb)', 0xd),
    0xe: InstWord('vsts', 'ra, disp(rb)', 0xe),
    0xf: InstWord('vstd', 'ra, disp(rb)', 0xf),
    0x17: InstWord('log3r', 'ra, rb, rc, rd', 0x17),
    0x1f: InstWord('vlog3r', 'ra, rb, rc, rd', 0x1f),
    0x20: InstWord('ldbu', 'ra, disp(rb)', 0x20),
    0x21: InstWord('ldhu', 'ra, disp(rb)', 0x21),
    0x22: InstWord('ldw', 'ra, disp(rb)', 0x22),
    0x23: InstWord('ldl', 'ra, disp(rb)', 0x23),
    0x26: InstWord('flds', 'ra, disp(rb)', 0x26),
    0x28: InstWord('stb', 'ra, disp(rb)', 0x28),
    0x29: InstWord('sth', 'ra, disp(rb)', 0x29),
    0x2a: InstWord('stw', 'ra, disp(rb)', 0x2a),
    0x2b: InstWord('stl', 'ra, disp(rb)', 0x2b),
    0x2e: InstWord('fsts', 'ra, disp(rb)', 0x2e),
    0x24: InstWord('vldr', 'ra, disp(rb)', 0x24),
    0x27: InstWord('ldder', 'ra, disp(rb)', 0x27),
    0x2c: InstWord('vldc', 'ra, disp(rb)', 0x2c),
    0x2f: InstWord('lddec', 'ra, disp(rb)', 0x2f),
    0x30: InstWord('beq', 'ra, disp', 0x30),
    0x31: InstWord('bne', 'ra, disp', 0x31),
    0x32: InstWord('blt', 'ra, disp', 0x32),
    0x33: InstWord('ble', 'ra, disp', 0x33),
    0x34: InstWord('bgt', 'ra, disp', 0x34),
    0x35: InstWord('bge', 'ra, disp', 0x35),
    0x38: InstWord('fbeq', 'ra, disp', 0x38),
    0x39: InstWord('fbne', 'ra, disp', 0x39),
    0x3a: InstWord('fblt', 'ra, disp', 0x3a),
    0x3b: InstWord('fble', 'ra, disp', 0x3b),
    0x3c: InstWord('fbgt', 'ra, disp', 0x3c),
    0x3d: InstWord('fbge', 'ra, disp', 0x3d),
    0x3e: InstWord('ldi', 'ra, disp(rb)', 0x3e),
    0x3f: InstWord('ldih', 'ra, disp(rb)', 0x3f),
    0x0: {
        0x2: InstWord('class_st', 'ra', 0x0, 0x2),
        0x4: InstWord('class_wr', 'ra, rb, rc', 0x0, 0x4),
        0x5: InstWord('class_rd', 'rc, rd', 0x0, 0x5),
        0xc: InstWord('class_wr', 'ra, ic', 0x0, 0xc),
        0xd: InstWord('class_rd', 'ic, rd', 0x0, 0xd),
        0x10: InstWord('selldw', 'ra, rb, ic, rd', 0x0, 0x10),
        0x20: InstWord('codc_search', 'ra, rb, ic, rd', 0x0, 0x20),
        0x21: InstWord('codc_fetch', 'ra, rb, ic, rd', 0x0, 0x21),
        0x22: InstWord('codc_chaddr', 'ra, rb, ic, rd', 0x0, 0x22),
        0x23: InstWord('codc_ldmaddr', 'rb, ic, rd', 0x0, 0x23),
        0x24: InstWord('codc_tag', 'rb, ic, rd', 0x0, 0x24),
        0x28: InstWord('codc_search', 'ra, rb, rd', 0x0, 0x28),
        0x29: InstWord('codc_fetch', 'ra, rb, rd', 0x0, 0x29),
        0x2a: InstWord('codc_chaddr', 'ra, rb, rd', 0x0, 0x2a),
        0x2b: InstWord('codc_ldmaddr', 'ra, rb, rd', 0x0, 0x2b),
        0x2c: InstWord('codc_tag', 'ra, rb, rd', 0x0, 0x2c),
        0x30: InstWord('sbmd_start', '', 0x0, 0x30),
        0x31: InstWord('sbmd_end', '', 0x0, 0x31),
        0x32: InstWord('sbmd_break', '', 0x0, 0x32),
    },
    0x5: {
        0x1: InstWord('dma', 'ra, rb, rc', 0x5, 0x1),
        0x2: InstWord('wrch', 'ra, ib, rc', 0x5, 0x2),
    },
    0x6: {
        0x0: InstWord('memb', '', 0x6, 0x0),
        0x10: InstWord('synr', 'ra', 0x6, 0x10),
        0x11: InstWord('sync', 'ra', 0x6, 0x11),
        0x80: InstWord('halt', '', 0x6, 0x80),
        0x30: InstWord('beq_hint', 'ra', 0x6, 0x30),
        0x31: InstWord('bne_hint', 'ra', 0x6, 0x31),
        0x32: InstWord('blt_hint', 'ra', 0x6, 0x32),
        0x33: InstWord('ble_hint', 'ra', 0x6, 0x33),
        0x34: InstWord('bgt_hint', 'ra', 0x6, 0x34),
        0x35: InstWord('bge_hint', 'ra', 0x6, 0x35),
        0xfe: InstWord('rcsr', 'ra, index', 0x6, 0xfe),
        0xff: InstWord('wcsr', 'ra, index', 0x6, 0xff),
    },
    0x7: {
        0x0: InstWord('vmatch', 'ra, rb, rd', 0x7, 0x0),
    },
    0x8: {
        0x2: InstWord('faaw', 'ra, disp(rb)', 0x8, 0x2),
        0x3: InstWord('faal', 'ra, disp(rb)', 0x8, 0x3),
        0xa: InstWord('updt', 'ra, disp(rb)', 0x8, 0xa),
    },
    0x10: {
        0x0: InstWord('addw', 'ra, rb, rc', 0x10, 0x0),
        0x1: InstWord('subw', 'ra, rb, rc', 0x10, 0x1),
        0x8: InstWord('addl', 'ra, rb, rc', 0x10, 0x8),
        0x9: InstWord('subl', 'ra, rb, rc', 0x10, 0x9),
        0xa: InstWord('s4addl', 'ra, rb, rc', 0x10, 0xa),
        0xb: InstWord('s4subl', 'ra, rb, rc', 0x10, 0xb),
        0xc: InstWord('s8addl', 'ra, rb, rc', 0x10, 0xc),
        0xd: InstWord('s8subl', 'ra, rb, rc', 0x10, 0xd),
        0x10: InstWord('mulw', 'ra, rb, rc', 0x10, 0x10),
        0x11: InstWord('umulw', 'ra, rb, rc', 0x10, 0x11),
        0x18: InstWord('mull', 'ra, rb, rc', 0x10, 0x18),
        0x19: InstWord('umulh', 'ra, rb, rc', 0x10, 0x19),
        0x28: InstWord('cmpeq', 'ra, rb, rc', 0x10, 0x28),
        0x29: InstWord('cmplt', 'ra, rb, rc', 0x10, 0x29),
        0x2a: InstWord('cmple', 'ra, rb, rc', 0x10, 0x2a),
        0x2b: InstWord('cmpult', 'ra, rb, rc', 0x10, 0x2b),
        0x2c: InstWord('cmpule', 'ra, rb, rc', 0x10, 0x2c),
        0x48: InstWord('sll', 'ra, rb, rc', 0x10, 0x48),
        0x49: InstWord('srl', 'ra, rb, rc', 0x10, 0x49),
        0x4a: InstWord('sra', 'ra, rb, rc', 0x10, 0x4a),
        0x4b: InstWord('rotl', 'ra, rb, rc', 0x10, 0x4b),
        0x58: InstWord('ctpop', 'rb, rc', 0x10, 0x58),
        0x59: InstWord('ctlz', 'rb, rc', 0x10, 0x59),
        0x5a: InstWord('cttz', 'rb, rc', 0x10, 0x5a),
        0x68: InstWord('zap', 'ra, rb, rc', 0x10, 0x68),
        0x69: InstWord('zapnot', 'ra, rb, rc', 0x10, 0x69),
        0x6a: InstWord('sextb', 'rb, rc', 0x10, 0x6a),
        0x6b: InstWord('sexth', 'rb, rc', 0x10, 0x6b),
        0xa0: InstWord('log2x0', 'ra, rb, rc', 0x10, 0xa0),
        0xa1: InstWord('log2x1', 'ra, rb, rc', 0x10, 0xa1),
        0xa2: InstWord('log2x2', 'ra, rb, rc', 0x10, 0xa2),
        0xa3: InstWord('log2x3', 'ra, rb, rc', 0x10, 0xa3),
        0xa4: InstWord('log2x4', 'ra, rb, rc', 0x10, 0xa4),
        0xa5: InstWord('log2x5', 'ra, rb, rc', 0x10, 0xa5),
        0xa6: InstWord('log2x6', 'ra, rb, rc', 0x10, 0xa6),
        0xa7: InstWord('log2x7', 'ra, rb, rc', 0x10, 0xa7),
        0xa8: InstWord('log2x8', 'ra, rb, rc', 0x10, 0xa8),
        0xa9: InstWord('log2x9', 'ra, rb, rc', 0x10, 0xa9),
        0xaa: InstWord('log2xa', 'ra, rb, rc', 0x10, 0xaa),
        0xab: InstWord('log2xb', 'ra, rb, rc', 0x10, 0xab),
        0xac: InstWord('log2xc', 'ra, rb, rc', 0x10, 0xac),
        0xad: InstWord('log2xd', 'ra, rb, rc', 0x10, 0xad),
        0xae: InstWord('log2xe', 'ra, rb, rc', 0x10, 0xae),
        0xaf: InstWord('log2xf', 'ra, rb, rc', 0x10, 0xaf),
    },
    0x11: {
        0x0: InstWord('seleq', 'ra, rb, rc, rd', 0x11, 0x0),
        0x3: InstWord('selle', 'ra, rb, rc, rd', 0x11, 0x3),
        0x4: InstWord('sellt', 'ra, rb, rc, rd', 0x11, 0x4),
    },
    0x12: {
        0x0: InstWord('addw', 'ra, ib, rc', 0x12, 0x0),
        0x1: InstWord('subw', 'ra, ib, rc', 0x12, 0x1),
        0x8: InstWord('addl', 'ra, ib, rc', 0x12, 0x8),
        0x9: InstWord('subl', 'ra, ib, rc', 0x12, 0x9),
        0xa: InstWord('s4addl', 'ra, ib, rc', 0x12, 0xa),
        0xb: InstWord('s4subl', 'ra, ib, rc', 0x12, 0xb),
        0xc: InstWord('s8addl', 'ra, ib, rc', 0x12, 0xc),
        0xd: InstWord('s8subl', 'ra, ib, rc', 0x12, 0xd),
        0x10: InstWord('mulw', 'ra, ib, rc', 0x12, 0x10),
        0x11: InstWord('umulw', 'ra, ib, rc', 0x12, 0x11),
        0x18: InstWord('mull', 'ra, ib, rc', 0x12, 0x18),
        0x19: InstWord('umulh', 'ra, ib, rc', 0x12, 0x19),
        0x28: InstWord('cmpeq', 'ra, ib, rc', 0x12, 0x28),
        0x29: InstWord('cmplt', 'ra, ib, rc', 0x12, 0x29),
        0x2a: InstWord('cmple', 'ra, ib, rc', 0x12, 0x2a),
        0x2b: InstWord('cmpult', 'ra, ib, rc', 0x12, 0x2b),
        0x2c: InstWord('cmpule', 'ra, ib, rc', 0x12, 0x2c),
        0x48: InstWord('sll', 'ra, ib, rc', 0x12, 0x48),
        0x49: InstWord('srl', 'ra, ib, rc', 0x12, 0x49),
        0x4a: InstWord('sra', 'ra, ib, rc', 0x12, 0x4a),
        0x4b: InstWord('rotl', 'ra, ib, rc', 0x12, 0x4b),
        0x68: InstWord('zap', 'ra, ib, rc', 0x12, 0x68),
        0x69: InstWord('zapnot', 'ra, ib, rc', 0x12, 0x69),
        0x6a: InstWord('sextb', 'ib, rc', 0x12, 0x6a),
        0x6b: InstWord('sexth', 'ib, rc', 0x12, 0x6b),
        0xa0: InstWord('log2x0', 'ra, ib, rc', 0x12, 0xa0),
        0xa1: InstWord('log2x1', 'ra, ib, rc', 0x12, 0xa1),
        0xa2: InstWord('log2x2', 'ra, ib, rc', 0x12, 0xa2),
        0xa3: InstWord('log2x3', 'ra, ib, rc', 0x12, 0xa3),
        0xa4: InstWord('log2x4', 'ra, ib, rc', 0x12, 0xa4),
        0xa5: InstWord('log2x5', 'ra, ib, rc', 0x12, 0xa5),
        0xa6: InstWord('log2x6', 'ra, ib, rc', 0x12, 0xa6),
        0xa7: InstWord('log2x7', 'ra, ib, rc', 0x12, 0xa7),
        0xa8: InstWord('log2x8', 'ra, ib, rc', 0x12, 0xa8),
        0xa9: InstWord('log2x9', 'ra, ib, rc', 0x12, 0xa9),
        0xaa: InstWord('log2xa', 'ra, ib, rc', 0x12, 0xaa),
        0xab: InstWord('log2xb', 'ra, ib, rc', 0x12, 0xab),
        0xac: InstWord('log2xc', 'ra, ib, rc', 0x12, 0xac),
        0xad: InstWord('log2xd', 'ra, ib, rc', 0x12, 0xad),
        0xae: InstWord('log2xe', 'ra, ib, rc', 0x12, 0xae),
        0xaf: InstWord('log2xf', 'ra, ib, rc', 0x12, 0xaf),
    },
    0x13: {
        0x0: InstWord('seleq', 'ra, ib, rc, rd', 0x13, 0x0),
        0x3: InstWord('selle', 'ra, ib, rc, rd', 0x13, 0x3),
        0x4: InstWord('sellt', 'ra, ib, rc, rd', 0x13, 0x4),
    },
    0x18: {
        0x0: InstWord('fadds', 'ra, rb, rc', 0x18, 0x0),
        0x1: InstWord('faddd', 'ra, rb, rc', 0x18, 0x1),
        0x2: InstWord('fsubs', 'ra, rb, rc', 0x18, 0x2),
        0x3: InstWord('fsubd', 'ra, rb, rc', 0x18, 0x3),
        0x4: InstWord('fmuls', 'ra, rb, rc', 0x18, 0x4),
        0x5: InstWord('fmuld', 'ra, rb, rc', 0x18, 0x5),
        0x6: InstWord('fdivs', 'ra, rb, rc', 0x18, 0x6),
        0x7: InstWord('fdivd', 'ra, rb, rc', 0x18, 0x7),
        0x8: InstWord('fsqrts', 'rb, rc', 0x18, 0x8),
        0x9: InstWord('fsqrtd', 'rb, rc', 0x18, 0x9),
        0x10: InstWord('fcmpeq', 'ra, rb, rc', 0x18, 0x10),
        0x11: InstWord('fcmple', 'ra, rb, rc', 0x18, 0x11),
        0x12: InstWord('fcmplt', 'ra, rb, rc', 0x18, 0x12),
        0x13: InstWord('fcmpun', 'ra, rb, rc', 0x18, 0x13),
        0x20: InstWord('fcvtsd', 'rb, rc', 0x18, 0x20),
        0x21: InstWord('fcvtds', 'rb, rc', 0x18, 0x21),
        0x26: InstWord('fcvtdlr', 'ra, ib, rc', 0x18, 0x26),
        0x27: InstWord('fcvtdl', 'rb, rc', 0x18, 0x27),
        0x2d: InstWord('fcvtls', 'rb, rc', 0x18, 0x2d),
        0x2f: InstWord('fcvtld', 'rb, rc', 0x18, 0x2f),
        0x30: InstWord('fcpys', 'ra, rb, rc', 0x18, 0x30),
        0x31: InstWord('fcpyse', 'ra, rb, rc', 0x18, 0x31),
        0x32: InstWord('fcpysn', 'ra, rb, rc', 0x18, 0x32),
        0x50: InstWord('rfpcr', 'rc', 0x18, 0x50),
        0x51: InstWord('wfpcr', 'ra', 0x18, 0x51),
    },
    0x19: {
        0x0: InstWord('fmas', 'ra, rb, rc, rd', 0x19, 0x0),
        0x1: InstWord('fmad', 'ra, rb, rc, rd', 0x19, 0x1),
        0x2: InstWord('fmss', 'ra, rb, rc, rd', 0x19, 0x2),
        0x3: InstWord('fmsd', 'ra, rb, rc, rd', 0x19, 0x3),
        0x4: InstWord('fnmas', 'ra, rb, rc, rd', 0x19, 0x4),
        0x5: InstWord('fnmad', 'ra, rb, rc, rd', 0x19, 0x5),
        0x6: InstWord('fnmss', 'ra, rb, rc, rd', 0x19, 0x6),
        0x7: InstWord('fnmsd', 'ra, rb, rc, rd', 0x19, 0x7),
        0x10: InstWord('fseleq', 'ra, rb, rc, rd', 0x19, 0x10),
        0x12: InstWord('fsellt', 'ra, rb, rc, rd', 0x19, 0x12),
        0x13: InstWord('fselle', 'ra, rb, rc, rd', 0x19, 0x13),
    },
    0x1a: {
        0x0: InstWord('vaddw', 'ra, rb, rc', 0x1a, 0x0),
        0x1: InstWord('vsubw', 'ra, rb, rc', 0x1a, 0x1),
        0x8: InstWord('vsllw', 'ra, rb, rc', 0x1a, 0x8),
        0x9: InstWord('vsrlw', 'ra, rb, rc', 0x1a, 0x9),
        0xa: InstWord('vsraw', 'ra, rb, rc', 0x1a, 0xa),
        0xb: InstWord('vrotlw', 'ra, rb, rc', 0x1a, 0xb),
        0xe: InstWord('vaddl', 'ra, rb, rc', 0x1a, 0xe),
        0xf: InstWord('vsubl', 'ra, rb, rc', 0x1a, 0xf),
        0x20: InstWord('vaddw', 'ra, ib, rc', 0x1a, 0x20),
        0x21: InstWord('vsubw', 'ra, ib, rc', 0x1a, 0x21),
        0x28: InstWord('vsllw', 'ra, ib, rc', 0x1a, 0x28),
        0x29: InstWord('vsrlw', 'ra, ib, rc', 0x1a, 0x29),
        0x2a: InstWord('vsraw', 'ra, ib, rc', 0x1a, 0x2a),
        0x2b: InstWord('vrotlw', 'ra, ib, rc', 0x1a, 0x2b),
        0x2e: InstWord('vaddl', 'ra, ib, rc', 0x1a, 0x2e),
        0x2f: InstWord('vsubl', 'ra, ib, rc', 0x1a, 0x2f),
        0xc: InstWord('sllow', 'ra, rb, rc', 0x1a, 0xc),
        0xd: InstWord('srlow', 'ra, rb, rc', 0x1a, 0xd),
        0x10: InstWord('uaddo_carry', 'ra, rb, rc', 0x1a, 0x10),
        0x11: InstWord('usubo_carry', 'ra, rb, rc', 0x1a, 0x11),
        0x12: InstWord('uaddo_take_carry', 'ra, rb, rc', 0x1a, 0x12),
        0x13: InstWord('usubo_take_carry', 'ra, rb, rc', 0x1a, 0x13),
        0x14: InstWord('addo_carry', 'ra, rb, rc', 0x1a, 0x14),
        0x15: InstWord('subo_carry', 'ra, rb, rc', 0x1a, 0x15),
        0x16: InstWord('addo_take_carry', 'ra, rb, rc', 0x1a, 0x16),
        0x17: InstWord('subo_take_carry', 'ra, rb, rc', 0x1a, 0x17),
        0x50: InstWord('umulqa', 'ra, rb, rc', 0x1a, 0x50),
        0x2c: InstWord('sllow', 'ra, ib, rc', 0x1a, 0x2c),
        0x2d: InstWord('srlow', 'ra, ib, rc', 0x1a, 0x2d),
        0x30: InstWord('uaddo_carry', 'ra, ib, rc', 0x1a, 0x30),
        0x31: InstWord('usubo_carry', 'ra, ib, rc', 0x1a, 0x31),
        0x32: InstWord('uaddo_take_carry', 'ra, ib, rc', 0x1a, 0x32),
        0x33: InstWord('usubo_take_carry', 'ra, ib, rc', 0x1a, 0x33),
        0x34: InstWord('addo_carry', 'ra, ib, rc', 0x1a, 0x34),
        0x35: InstWord('subo_carry', 'ra, ib, rc', 0x1a, 0x35),
        0x36: InstWord('addo_take_carry', 'ra, ib, rc', 0x1a, 0x36),
        0x37: InstWord('subo_take_carry', 'ra, ib, rc', 0x1a, 0x37),
        0x70: InstWord('umulqa', 'ra, ib, rc', 0x1a, 0x70),
        0x80: InstWord('vadds', 'ra, rb, rc', 0x1a, 0x80),
        0x81: InstWord('vaddd', 'ra, rb, rc', 0x1a, 0x81),
        0x82: InstWord('vsubs', 'ra, rb, rc', 0x1a, 0x82),
        0x83: InstWord('vsubd', 'ra, rb, rc', 0x1a, 0x83),
        0x84: InstWord('vmuls', 'ra, rb, rc', 0x1a, 0x84),
        0x85: InstWord('vmuld', 'ra, rb, rc', 0x1a, 0x85),
        0x86: InstWord('vdivs', 'ra, rb, rc', 0x1a, 0x86),
        0x87: InstWord('vdivd', 'ra, rb, rc', 0x1a, 0x87),
        0x88: InstWord('vsqrts', 'rb, rc', 0x1a, 0x88),
        0x89: InstWord('vsqrtd', 'rb, rc', 0x1a, 0x89),
        0x8c: InstWord('vfcmpeq', 'ra, rb, rc', 0x1a, 0x8c),
        0x8d: InstWord('vfcmple', 'ra, rb, rc', 0x1a, 0x8d),
        0x8e: InstWord('vfcmplt', 'ra, rb, rc', 0x1a, 0x8e),
        0x8f: InstWord('vfcmpun', 'ra, rb, rc', 0x1a, 0x8f),
        0x90: InstWord('vcpys', 'ra, rb, rc', 0x1a, 0x90),
        0x91: InstWord('vcpyse', 'ra, rb, rc', 0x1a, 0x91),
        0x92: InstWord('vcpysn', 'ra, rb, rc', 0x1a, 0x92),
        0xa0: InstWord('vlog2x0', 'ra, rb, rc', 0x1a, 0xa0),
        0xa1: InstWord('vlog2x1', 'ra, rb, rc', 0x1a, 0xa1),
        0xa2: InstWord('vlog2x2', 'ra, rb, rc', 0x1a, 0xa2),
        0xa3: InstWord('vlog2x3', 'ra, rb, rc', 0x1a, 0xa3),
        0xa4: InstWord('vlog2x4', 'ra, rb, rc', 0x1a, 0xa4),
        0xa5: InstWord('vlog2x5', 'ra, rb, rc', 0x1a, 0xa5),
        0xa6: InstWord('vlog2x6', 'ra, rb, rc', 0x1a, 0xa6),
        0xa7: InstWord('vlog2x7', 'ra, rb, rc', 0x1a, 0xa7),
        0xa8: InstWord('vlog2x8', 'ra, rb, rc', 0x1a, 0xa8),
        0xa9: InstWord('vlog2x9', 'ra, rb, rc', 0x1a, 0xa9),
        0xaa: InstWord('vlog2xa', 'ra, rb, rc', 0x1a, 0xaa),
        0xab: InstWord('vlog2xb', 'ra, rb, rc', 0x1a, 0xab),
        0xac: InstWord('vlog2xc', 'ra, rb, rc', 0x1a, 0xac),
        0xad: InstWord('vlog2xd', 'ra, rb, rc', 0x1a, 0xad),
        0xae: InstWord('vlog2xe', 'ra, rb, rc', 0x1a, 0xae),
        0xaf: InstWord('vlog2xf', 'ra, rb, rc', 0x1a, 0xaf),
        0xb0: InstWord('vlog2x0', 'ra, ib, rc', 0x1a, 0xb0),
        0xb1: InstWord('vlog2x1', 'ra, ib, rc', 0x1a, 0xb1),
        0xb2: InstWord('vlog2x2', 'ra, ib, rc', 0x1a, 0xb2),
        0xb3: InstWord('vlog2x3', 'ra, ib, rc', 0x1a, 0xb3),
        0xb4: InstWord('vlog2x4', 'ra, ib, rc', 0x1a, 0xb4),
        0xb5: InstWord('vlog2x5', 'ra, ib, rc', 0x1a, 0xb5),
        0xb6: InstWord('vlog2x6', 'ra, ib, rc', 0x1a, 0xb6),
        0xb7: InstWord('vlog2x7', 'ra, ib, rc', 0x1a, 0xb7),
        0xb8: InstWord('vlog2x8', 'ra, ib, rc', 0x1a, 0xb8),
        0xb9: InstWord('vlog2x9', 'ra, ib, rc', 0x1a, 0xb9),
        0xba: InstWord('vlog2xa', 'ra, ib, rc', 0x1a, 0xba),
        0xbb: InstWord('vlog2xb', 'ra, ib, rc', 0x1a, 0xbb),
        0xbc: InstWord('vlog2xc', 'ra, ib, rc', 0x1a, 0xbc),
        0xbd: InstWord('vlog2xd', 'ra, ib, rc', 0x1a, 0xbd),
        0xbe: InstWord('vlog2xe', 'ra, ib, rc', 0x1a, 0xbe),
        0xbf: InstWord('vlog2xf', 'ra, ib, rc', 0x1a, 0xbf),
    },
    0x1b: {
        0x0: InstWord('vmas', 'ra, rb, rc, rd', 0x1b, 0x0),
        0x1: InstWord('vmad', 'ra, rb, rc, rd', 0x1b, 0x1),
        0x2: InstWord('vmss', 'ra, rb, rc, rd', 0x1b, 0x2),
        0x3: InstWord('vmsd', 'ra, rb, rc, rd', 0x1b, 0x3),
        0x4: InstWord('vnmas', 'ra, rb, rc, rd', 0x1b, 0x4),
        0x5: InstWord('vnmad', 'ra, rb, rc, rd', 0x1b, 0x5),
        0x6: InstWord('vnmss', 'ra, rb, rc, rd', 0x1b, 0x6),
        0x7: InstWord('vnmsd', 'ra, rb, rc, rd', 0x1b, 0x7),
        0x10: InstWord('vseleq', 'ra, rb, rc, rd', 0x1b, 0x10),
        0x12: InstWord('vsellt', 'ra, rb, rc, rd', 0x1b, 0x12),
        0x13: InstWord('vselle', 'ra, rb, rc, rd', 0x1b, 0x13),
        0x20: InstWord('vinsw', 'ra, rb, ic, rd', 0x1b, 0x20),
        0x21: InstWord('vinsf', 'ra, rb, ic, rd', 0x1b, 0x21),
        0x22: InstWord('vextw', 'ra, ic, rd', 0x1b, 0x22),
        0x23: InstWord('vextf', 'ra, ic, rd', 0x1b, 0x23),
        0x26: InstWord('vshfw', 'ra, rb, rc, rd', 0x1b, 0x26),
        0x27: InstWord('vshff', 'ra, rb, rc, rd', 0x1b, 0x27),
        0x28: InstWord('vshff', 'ra, rb, ic, rd', 0x1b, 0x28),
    },
    0x25: {
        0x0: InstWord('ldw_ul', 'ra, disp(rb)', 0x25, 0x0),
        0x1: InstWord('ldw_uh', 'ra, disp(rb)', 0x25, 0x1),
        0x2: InstWord('ldl_ul', 'ra, disp(rb)', 0x25, 0x2),
        0x3: InstWord('ldl_uh', 'ra, disp(rb)', 0x25, 0x3),
        0x8: InstWord('stw_ul', 'ra, disp(rb)', 0x25, 0x8),
        0x9: InstWord('stw_uh', 'ra, disp(rb)', 0x25, 0x9),
        0xa: InstWord('stl_ul', 'ra, disp(rb)', 0x25, 0xa),
        0xb: InstWord('stl_uh', 'ra, disp(rb)', 0x25, 0xb),
    },
    0x1c: {
        0x0: InstWord('vldw_ul', 'ra, disp(rb)', 0x1c, 0x0),
        0x1: InstWord('vldw_uh', 'ra, disp(rb)', 0x1c, 0x1),
        0x2: InstWord('vlds_ul', 'ra, disp(rb)', 0x1c, 0x2),
        0x3: InstWord('vlds_uh', 'ra, disp(rb)', 0x1c, 0x3),
        0x4: InstWord('vldd_ul', 'ra, disp(rb)', 0x1c, 0x4),
        0x5: InstWord('vldd_uh', 'ra, disp(rb)', 0x1c, 0x5),
        0x8: InstWord('vstw_ul', 'ra, disp(rb)', 0x1c, 0x8),
        0x9: InstWord('vstw_uh', 'ra, disp(rb)', 0x1c, 0x9),
        0xa: InstWord('vsts_ul', 'ra, disp(rb)', 0x1c, 0xa),
        0xb: InstWord('vsts_uh', 'ra, disp(rb)', 0x1c, 0xb),
        0xc: InstWord('vstd_ul', 'ra, disp(rb)', 0x1c, 0xc),
        0xd: InstWord('vstd_uh', 'ra, disp(rb)', 0x1c, 0xd),
    },
    0x2d: {
        0x0: InstWord('getr', 'ra', 0x2d, 0x0),
        0x1: InstWord('getc', 'ra', 0x2d, 0x1),
        0x2: InstWord('putr', 'ra, rb', 0x2d, 0x2),
        0x3: InstWord('putc', 'ra, rb', 0x2d, 0x3),
        0x12: InstWord('putr', 'ra, idest', 0x2d, 0x12),
        0x13: InstWord('putc', 'ra, idest', 0x2d, 0x13),
    }
}
RCSR = InstWord('rcsr', 'ra, index', 0x6, 0xfe)
WCSR = InstWord('wcsr', 'ra, index', 0x6, 0xff)
VSHFFIC = InstWord('vshff', 'ra, rb, ic, rd', 0x1b, 0x28 >> 3)

def lookup_inst_by_op_func(op, func = None):
    if func is not None:
        if op == 0x6:
            if (func & 0xff00) == 0xff00:
                return WCSR
            elif (func & 0xff00) == 0xfe00:
                return RCSR
        elif op == 0x1b and (func & 0x28):
            return VSHFFIC
    if (type(OPINST[op]) == dict):
        return OPINST[op][func]
    else:
        return OPINST[op]
def lookup_inst_by_bin(inst):
    op = (inst >> 26) & 63
    if op == 0x6:
        misc = MiscInst(inst)
        if (misc.func & 0xff00) == 0xff00:
            return WCSR
        elif (misc.func & 0xff00) == 0xfe00:
            # print("0xfe")
            return RCSR
    elif op == 0x1b:
        vec3 = Vec3Inst(inst)
        if vec3.func & 0x28:
            return VSHFFIC
    if (type(OPINST[op]) == dict):
        inst_class = get_class_by_bin(inst)
        instobj = inst_class(inst)
        return OPINST[instobj.op][instobj.func]
    else:
        return OPINST[op]
def parse_inst(inst):
    inst_class = get_class_by_bin(inst)
    return inst_class(inst)
